<?php

require_once dirname(__FILE__) . '/ConfigStore.php';
require_once dirname(__FILE__) . '/SessionStore.php';
require_once dirname(__FILE__) . '/CookieStore.php';
require_once dirname(__FILE__) . '/Config.php';

/**
 * Store for OAuth tokens received by client app from server.
 */
class GG_API_Store {

	private static $instance;

	/**
	 * @return GG_API_Store Singleton. Default store based on default GG_API_Config.
	 */
    public static function getDefault() {
        return isset(self::$instance) ?
			self::$instance :
			self::$instance = self::newByConfig();
    }

	/**
	 * @var GG_API_Config
	 */
	private $config = null;

	/**
	 * @var array Array that holds values for this store. It can be $_SESSION,
	 * $config array, $_COOKIE, etc.
	 */
	private $arrayStore;

	protected function __construct() {
	}

	/**
	 * @param GG_API_Config $config
	 */
	public static function newByConfig($config = null) {
		$instance = null;
		if ($config === null) {
			$config = GG_API_Config::getDefault();
		}
		if ($config instanceof GG_API_Config) {
			$storeConfig = $config->getStore();
			if (array_key_exists('type', $storeConfig)) {
				$storeType = $storeConfig['type'];
				$instance = self::newByType($storeType);
				if ($instance instanceof self) {
					$instance->setConfig($config);
				}
			}
		}
		return $instance;
	}

	/**
	 * @param string $storeType Valid values: null, "none", "config", "session", "cookies".
	 * @return GG_API_Store null, GG_API_Store or its subclass depending on $storeType.
	 */
	private static function newByType($storeType = 'session') {
		$instance = null;
		if (!is_string($storeType) || $storeType === 'none') {
			$instance = new self();
		} else if ($storeType === 'config') {
			$instance = new GG_API_ConfigStore();
		} else if ($storeType === 'session') {
			$instance = new GG_API_SessionStore();
		} else if ($storeType === 'cookies' || $storeType === 'cookie') {
			$instance = new GG_API_CookieStore();
		}
		return $instance;
	}

	/**
	 * @param GG_API_Config $config Config that will be used in this store.
	 */
	public function setConfig($config) {
		if ($config instanceof GG_API_Config) {
			$this->config = $config;
		}
	}

	/**
	 * @return GG_API_Config
	 */
	public function getConfig() {
		return $this->config;
	}

	/**
	 * @param array $arrayStore Array that holds values for this store.
	 */
	protected function setArrayStore($arrayStore) {
		if (is_array($arrayStore)) {
			$this->arrayStore = $arrayStore;
		}
	}

	/**
	 * @return array Array that holds values for this store.
	 */
	protected function getArrayStore() {
		$arrayStore = $this->arrayStore;
		if (!is_array($arrayStore)) {
			$arrayStore = array();
		}
		return $arrayStore;
	}

	/**
	 * @param string $key
	 * @return mixed
	 */
	protected function getArrayStoreValue($key) {
		$value = null;
		$store = $this->getArrayStore();
		if (array_key_exists($key, $store)) {
			$value = $store[$key];
		}
		return $value;
	}

	/**
	 * @return array Array that holds config for this store. See example
	 * of this array in file [config.inc.php] under variable $config
	 * under key "store".
	 */
	protected function getStoreConfigArray() {
		$result = null;
		$config = $this->getConfig();
		if ($config instanceof GG_API_Config) {
			$result = $config->getStore();
		}
		if (!is_array($result)) {
			$result = array();
		}
		return $result;
	}

	protected function getKeyName($key) {
		$keyName = null;
		$storeConfig = $this->getStoreConfigArray();
		if (array_key_exists('keyNames', $storeConfig)) {
			$keyNames = $storeConfig['keyNames'];
			if (array_key_exists($key, $keyNames)) {
				$keyName = $keyNames[$key];
			}
		}
		return $keyName;
	}

	public function getKeyNameOfOauthTokenSecret() {
		return $this->getKeyName('oauthTokenSecret');
	}

	public function getKeyNameOfOauthToken() {
		return $this->getKeyName('oauthToken');
	}

	public function getOauthToken() {
		return $this->getArrayStoreValue($this->getKeyNameOfOauthToken());
	}

	public function getOauthTokenSecret() {
		return $this->getArrayStoreValue($this->getKeyNameOfOauthTokenSecret());
	}
}

?>
